// es6 --  layer
// 作者 王欢
// 开始日期 2019-12-20
// 简化小程序弹框 api

const { $copy,$toClass } = require("./common");
/* 
    $log(opts:String[,ass:Number|Object|Function]);
    轻提示 基于 wx.showToast  支持promise
    时间参数 为 毫秒  默认消失时间为 2000ms
    使用方法
    推荐第一种 promise调用
    //"第一种"
    $log("你好").then(()=>{
        console.log("我很好啊");
    }) 
    //"第二种"
    $log("你好",()=>{
        console.log("我很好啊");
    }); 
    //"第三种" , 3000ms关闭
    /* $log("你好",3000).then(()=>{
        console.log("我很好啊");
    }); 
    //"第四种" , 3000ms关闭  拼接额额外参数
    $log("你好",{
        icon:"yes"
    }).then(()=>{
        console.log("我很好啊");
    }); 
*/
function $log(opts, ass) {
    return new Promise((resolve, reject) => {
        if (opts) {
            // 默认关闭时间
            let defaultOpts = {
                // 除去 图标
                icon: "none",
                // 显示遮罩层
                mask: false,
                // 默认调用成功后  关闭时间
                duration: 2000
            };
            // 对第一个参数进行合并
            let optsType = $toClass(opts);
            // 如果是字符串 最常用  合并到 title参数
            if (optsType == "String") {
                defaultOpts.title = opts;

            }
            // 暂时取消这个判断
            // 如果是对象  直接进行合并
            else if (optsType == "Object") {
                $copy(defaultOpts, opts);
            } 
            else {
                throw new TypeError("the opts must be String ");
            }
            // endFun 只有第二个参数为function类型会在promise之前 提示消失之后执行  
            let endFun;
            if (ass) {
                // 对第二个参数进行合并
                let assType = $toClass(ass);
                switch (assType) {
                    // 如果是数字  合并到 duration参数
                    case "Number":
                        defaultOpts.duration = ass; break;
                    // 如果是函数  在提示消失后执行    
                    case "Function":
                        endFun = ass; break;
                    // 如果是对象   直接合并
                    case "Object":
                        $copy(defaultOpts, ass); break;
                    default:
                        throw new TypeError("the opts must be Number Object or Function");

                }
            }
            let { title, duration } = defaultOpts;
            if (title) {
                // 返回一个promise对象
                wx.showToast(
                    $copy(defaultOpts, {
                        success() {
                            setTimeout(() => {
                                // 如果回调函数存在 在 promise then 之前执行
                                endFun && endFun();
                                resolve();
                            }, duration);
                        },
                        fail() {
                            reject();
                        }
                    })
                );
            } else {
                throw new ReferenceError("the options title is must be required");
            }
        } else {
            throw new ReferenceError("the opts must be required");
        }
    });


}

/* 
    $showModal(opts:String:Object[,ass:Object]);
    // 对话框 基于 wx.showModal  支持promise
    // 时间参数 为 毫秒
    // 对话框原型
    // yes 与 no  在promise之前调用 

*/
function $showModal(opts, ass) {
    return new Promise((resolve, reject) => {
        if (opts) {
            let defaultOpts = {
                // 对话标题
                // title,
                // 对话内容
                // content,
            };
            // 对第一个参数进行合并
            let optsType = $toClass(opts);
            // 如果是字符串 最常用  合并到 title参数
            if (optsType == "String") {
                defaultOpts.content = opts;
                // 如果是对象  直接进行合并
            } else if (optsType == "Object") {
                $copy(defaultOpts, opts);
            } else {
                throw new TypeError("the opts must be String or Object");
            }
            // 如果第二个参数存在且为对象则合并  否 忽略
            if (ass) {
                if ($toClass(ass) == "Object") {
                    $copy(defaultOpts, ass);
                } else {
                    console.warn("the ass is not an object , ignored");
                }
            }
            let { content, showCancel } = defaultOpts;
            if (content) {
                wx.showModal(
                    $copy(defaultOpts, {
                        success(res) {
                            let { yes, no } = defaultOpts;
                            if (res.confirm) {
                                yes && yes();
                                resolve();
                            } else if (showCancel != false && res.cancel) {
                                no && no();
                                reject();
                            }
                        },
                        fail() {
                            reject("interface call failed");
                        }
                    })
                );
            } else {
                throw new ReferenceError("the options content is must be required");
            }
        } else {
            throw new ReferenceError("the opts must be required");
        }
    })
}

/* 
    _assFunc(opts:Function);
    // 给showmodal添加静态方法 返回一个正确函数 

*/
function _assFunc(opts) {
    if (opts && typeof opts == "function") {
        return opts;
    }
}

/* 
    $alert(opts:String:Object[,yes:Function]);
    alert 与 confirm 基于 $showModal 
    alert 与 confirm 都支持 promise对象
    alert,confrim 确定事件在 then
    额外添加 yes 与 no 回调函数 简单添加一个回调
    使用方法
    推荐第一种 promise调用
    //"第一种"
    $alert("你好").then(()=>{
        console.log("我很好啊");
    }) 
    //"第二种"
    $alert("你好",()=>{
        console.log("我很好啊");
    }); 
    //"第三种" , "复杂模式改变第一个参数为对象模式"
    $alert({
        title:"提示",
        content:"hellow"
    },()=>{
        console.log("我很好啊");
    }); 
 */
function $alert(opts, yes) {
    return $showModal(opts,
        {
            // 隐藏取消按钮
            showCancel: false,
            // 确定回调函数
            yes: _assFunc(yes)
        }
    );
}
/* 
    $confirm(opts:String|Object[,yes:Function,no:Function]);
    // 推荐第一种 promise调用
    // confrim 取消事件在 catch
    //"第一种"
    $confirm("你好").then(()=>{
        console.log("我很好啊");
    }).catch(()=>{
        console.log("不好了");
    })
    // //"第二种"
    $confirm("你好",()=>{
        console.log("我很好啊");
    },()=>{
        console.log("不好了");
    });
    //"第三种" , "复杂模式改变第一个参数为对象模式"
    $confirm({
        title:"提示",
        content:"hellow"
    },()=>{
        console.log("我很好啊");
    },()=>{
        console.log("不好了");
    })); 

*/

function $confirm(opts, yes, no) {
    // 直接传递参数  
    return $showModal(opts, {
        // 确定回调函数
        yes: _assFunc(yes),
        // 取消回调函数
        no: _assFunc(no)
    });
}

// 失败提示
/* 
	$fail(err:String|Error|Object)
*/
function $fail(err = "请求失败") {
    const errType = $toClass( err );
    if( errType === "Error" || errType === "Object" ){
        let errNotic =  err.message || err.errMsg || "未知错误";
        $log( errNotic );
        throw err;
    }else if( errType === "String" ){
        $log( err );
        throw Error( err );
    }else{
        throw TypeError(`the Error params type is must be String or Error , the params type is ${ errType }`);
    }
}
module.exports = {   
    $log
    ,$alert
    ,$confirm
    ,$fail
}